package com.vc.desktop.web.servlet;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.vc.Constants;

public class RemoteServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	private ConcurrentHashMap<String, String> remoteCache = new ConcurrentHashMap<String, String>();
	
	private static Map<String, String> urlMap = new HashMap<String, String>(5);
	
	static {
		urlMap.put("sell", Constants.URL.sell);
		urlMap.put("buy", Constants.URL.buy);
		urlMap.put("his", Constants.URL.his);
		urlMap.put("chart", Constants.URL.chart);
		urlMap.put("btc_cny", Constants.URL.btc2cny);
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String url = req.getParameter("url");
		String cacheKey = url;
		if (url == null) {
			String marketId = req.getParameter("marketId");
			String key = req.getParameter("key");
			url = String.format(urlMap.get(key), marketId);
			cacheKey = key + marketId;
		}
		HttpURLConnection conn = null;
		InputStream in = null;
		try {
			conn = getRemoteConnectionByURL(url);
			conn.connect();
			in = conn.getInputStream();
			String content = copy(in, resp.getOutputStream());
			remoteCache.put(cacheKey, content);
		} catch (Exception e) {
			System.out.println("Read from remote error: " + e.getMessage() + ", cacheKey = " + cacheKey);
			printLastContent(cacheKey, resp);
		} finally {
			if (in != null) {
				try {
					in.close();
					in = null;
				} catch (IOException e) {
					// ignore errors...
				}
			}
			if (conn != null) {
				conn.disconnect();
				conn = null;
			}
		}
	}
	
	private void printLastContent(String cacheKey, HttpServletResponse resp) throws IOException {
		String content = remoteCache.get(cacheKey);
		if (content != null) {
			System.out.println("Read content from cache: cacheKey = " + cacheKey);
			ServletOutputStream out = resp.getOutputStream();
			out.write(content.getBytes());
			out.flush();
		} else {
			System.out.println("No exist in cache: cacheKey = " + cacheKey);
		}
	}
	
	protected String copy(InputStream in, OutputStream out) throws IOException {
		byte[] buffer = new byte[512];
		int len = -1;
		StringBuilder sb = new StringBuilder();
		while ((len = in.read(buffer, 0, 512)) > 0) {
			out.write(buffer, 0, len);
			out.flush();
			sb.append(new String(buffer, 0, len));
		}
		return sb.toString();
	}
	
	protected HttpURLConnection getRemoteConnectionByURL(String urlString) throws IOException {
		try {
			URI uri = new URI(urlString);
			URL url = uri.toURL();
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setDoInput(true);
			conn.setConnectTimeout(30 * 1000);
			conn.setReadTimeout(180 * 1000);
			return conn;
		} catch (URISyntaxException e) {
			throw new IOException(e.getMessage(), e);
		}
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		this.doGet(req, resp);
	}

}
